package gant.ext

import org.apache.tools.ant.Project
import org.codehaus.gant.GantBinding
import org.codehaus.gant.GantBuilder
import org.codehaus.gant.GantState
import org.junit.BeforeClass
import org.junit.Test
import gant.ext.AntBindingFactory
import gant.ext.AntLoggerFacade

/**
 * Created by IntelliJ IDEA.
 * User: tbarker
 * Date: 4/9/12
 * Time: 1:26 PM
 */
class AntLoggerFacadeTest {

    def logger = new AntLoggerFacade()
    def slf4jLevel

    @Test
    void testLoggingForAllLevels() {
        logger.gantToSlf4j.keySet().each {
            doLoggingTest(Integer.valueOf(it))
        }
        logger = new AntLoggerFacade(builder: new GantBuilder())
    }

    @Test
    void testLogFormatter() {
        assert "${logger.SPACE_TO_LINE_UP_TO_ECHO}[info] foobar" == logger.formatLog("foobar", "info")
        logger.name = "gant"
        assert "${logger.SPACE_TO_LINE_UP_TO_ECHO}[info] foobar" == logger.formatLog("foobar", "info")
        logger.name = "bar"
        assert "${logger.SPACE_TO_LINE_UP_TO_ECHO}[info] bar - foobar" == logger.formatLog("foobar", "info")
    }

    void doLoggingTest(Integer state) {
        GantState.verbosity = state
        slf4jLevel = logger.gantToSlf4j[String.valueOf(state)]
        checkEnabled(state)
        checkNoArgLogging(state)
        checkOneArgLogging(state)
        checkTwoArgLogging(state)
        checkExceptionLogging(state)
    }

    void checkExceptionLogging(Integer integer) {
        Project project = AntBindingFactory.instance.binding.ant.project
        boolean logCalled = false
        project.metaClass.log = {String message, Throwable t, int priorityLevel ->
            assert message == "${AntLoggerFacade.SPACE_TO_LINE_UP_TO_ECHO}[${slf4jLevel}] foo"
            if (GantState.verbosity != GantState.SILENT) {
                assert priorityLevel == GantState.verbosity
            } else {
                assert priorityLevel - 1 == GantState.verbosity
            }
            logCalled = true
        }

        GantState.loggingLevel = integer
        logger."${slf4jLevel}"("foo", new RuntimeException("oops"))
        assert logCalled: "Could not run logging exception test for gant verbosity '${GantState.verbosity}' and slf4j level '${slf4jLevel}'"
    }

    void checkTwoArgLogging(Integer integer) {
        Project project = AntBindingFactory.instance.binding.ant.project
        boolean logCalled = false
        project.metaClass.log = {String message, int priorityLevel ->
            assert message == "${AntLoggerFacade.SPACE_TO_LINE_UP_TO_ECHO}[${slf4jLevel}] foobarbaz"
            if (GantState.verbosity != GantState.SILENT) {
                assert priorityLevel == GantState.verbosity
            } else {
                assert priorityLevel - 1 == GantState.verbosity
            }
            logCalled = true
        }

        GantState.loggingLevel = integer
        logger."${slf4jLevel}"("foo{}{}", "bar", "baz")
        assert logCalled: "Could not run two arg test for gant verbosity '${GantState.verbosity}' and slf4j level '${slf4jLevel}'"
    }

    void checkOneArgLogging(Integer integer) {
        Project project = AntBindingFactory.instance.binding.ant.project
        boolean logCalled = false
        project.metaClass.log = {String message, int priorityLevel ->
            assert message == "${AntLoggerFacade.SPACE_TO_LINE_UP_TO_ECHO}[${slf4jLevel}] foobar"
            if (GantState.verbosity != GantState.SILENT) {
                assert priorityLevel == GantState.verbosity
            } else {
                assert priorityLevel - 1 == GantState.verbosity
            }
            logCalled = true
        }

        GantState.loggingLevel = integer
        logger."${slf4jLevel}"("foo{}", "bar")
        assert logCalled: "Could not run one arg test for gant verbosity '${GantState.verbosity}' and slf4j level '${slf4jLevel}'"
    }

    void checkEnabled(Integer state) {
        def oldState = GantState.verbosity
        GantState.loggingLevel = GantState.NORMAL
        if (state <= GantState.NORMAL) {
            assert logger."${slf4jLevel}Enabled"
            if (state != GantState.SILENT && state != GantState.ERRORS_ONLY) {
                GantState.loggingLevel = GantState.SILENT
                assert !logger."${slf4jLevel}Enabled"
                GantState.loggingLevel = state
                assert logger."${slf4jLevel}Enabled"
            }
        } else {
            assert !logger."${slf4jLevel}Enabled"
            GantState.loggingLevel = state
            assert logger."${slf4jLevel}Enabled"
        }
        GantState.loggingLevel = oldState
    }

    void checkNoArgLogging(Integer state) {
        Project project = AntBindingFactory.instance.binding.ant.project
        GantState.loggingLevel = state
        boolean logCalled = false
        project.metaClass.log = {String message, int priorityLevel ->
            assert message == "${AntLoggerFacade.SPACE_TO_LINE_UP_TO_ECHO}[${slf4jLevel}] foo"
            if (GantState.SILENT != state) {
                assert priorityLevel == state
            } else {
                assert priorityLevel == GantState.ERRORS_ONLY
            }
            logCalled = true
        }
        assert !logCalled
        logger."${slf4jLevel}"("foo")
        assert logCalled: "logging at level ${slf4jLevel} was not called"
    }

    @BeforeClass
    static void setupAntLoggingFactory() {
        def binding = new GantBinding()

        AntBindingFactory.createInstance(binding)
    }

}


